﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Collections.Generic;
using System.ServiceModel.Description;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;

namespace MK.CRM.PluginQuickDeploy {

    public class Program {

        #region Members
        private static Uri _organizationUri;
        private static string _username;
        private static string _password;
        private static string _domain;
        private static string _assemblyName;
        private static string _pathToAssembly;
        private static bool _showLofAfterExecution;
        #endregion

        #region Main
        static void Main(string[] args) {
            ReadSettings();
            try {
                IOrganizationService service = GenerateService();
                EntityCollection retrievedAssemblies = RetrievePluginAssembly(service);
                UpdatePluginAssembly(service, retrievedAssemblies);
                if (_showLofAfterExecution) {
                    Console.WriteLine("\nClick any key to close window.");
                    Console.Read();
                }
            } catch (Exception ex) {
                Console.WriteLine("Error updating assembly - {0}", ex.ToString());
                Console.Read();
            }
        }
        #endregion

        #region Helpers
        private static void UpdatePluginAssembly(IOrganizationService service, EntityCollection retrievedAssemblies) {
            Console.WriteLine("Updating PluginAssembly...");
            if (retrievedAssemblies.Entities.Count > 0) {
                Entity myAssembly = retrievedAssemblies.Entities[0];

                string assemblyPathWithAssemblyName;
                if (string.IsNullOrWhiteSpace(_pathToAssembly)) {
                    assemblyPathWithAssemblyName = string.Format("{0}{1}", _assemblyName, ".dll");
                } else {
                    assemblyPathWithAssemblyName = string.Format("{0}{1}", _pathToAssembly, string.Format("{0}{1}", _assemblyName, ".dll"));
                }
                byte[] bytes = File.ReadAllBytes(assemblyPathWithAssemblyName);
                myAssembly["content"] = Convert.ToBase64String(bytes);
                service.Update(myAssembly);
                Console.WriteLine("Updating PluginAssembly finished.");
            } else {
                Console.WriteLine("Updating PluginAssembly was not required (assembly not found in crm).");
            }
        }

        private static EntityCollection RetrievePluginAssembly(IOrganizationService service) {
            Console.WriteLine("Retrieving PluginAssembly...");
            QueryExpression query = new QueryExpression("pluginassembly");
            query.ColumnSet = new ColumnSet("name");
            query.Criteria.Conditions.Add(new ConditionExpression("name", ConditionOperator.Equal, _assemblyName));
            EntityCollection retrievedAssemblies = service.RetrieveMultiple(query);
            Console.WriteLine("Retrieving PluginAssembly finished.");
            return retrievedAssemblies;
        }

        private static IOrganizationService GenerateService() {
            Console.WriteLine("Generating Service...");
            Uri homeRealmUri = null;
            ClientCredentials credentials = new ClientCredentials();
            credentials.Windows.ClientCredential = new System.Net.NetworkCredential(_username, _password, _domain);
            OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(_organizationUri, homeRealmUri, credentials, null);
            IOrganizationService service = (IOrganizationService)orgProxy;
            Console.WriteLine("Generating Service finished.");
            return service;
        }

        private static void ReadSettings() {
            try {
                Console.WriteLine("Reading settings...");
                _username = Properties.Settings.Default.Username;
                _password = Properties.Settings.Default.Password;
                _domain = Properties.Settings.Default.Domain;
                _organizationUri = new Uri(Properties.Settings.Default.OrganizationUri);
                _assemblyName = Properties.Settings.Default.CurrentAssemblyName;
                _pathToAssembly = Properties.Settings.Default.PathToAssembly;
                _showLofAfterExecution = Properties.Settings.Default.ShowLogAfterExecution;
                Console.WriteLine("Reading settings finished.");
            } catch (Exception ex) {
                Console.WriteLine("Error reading settings - {0}", ex.ToString());
                Console.Read();
            }
        }
        #endregion
    }
}
